2D Visualization笔记(X1) SciChart(一)

SciChart(3.1.4549版本)

目录

  • BindToDataSeriesSetView.xaml
  • NumericAxis
  • FastLineRenderableSeries
  • SciChartSurface
  • HighSpeedRenderSurface
  • ViewConverter
  • IRenderContext2D
  • IRenderPassData

摘要

  1. BindToDataSeriesSetView.xaml由NumericAxis(坐标轴), FastLineRenderableSeries(曲线), SciChartSurface(Chart区域)构成;
  2. SciChartSurface的DoDrawingLoop用到IRenderSurface2D(HighSpeedRenderSurfaceu实现, 用来获取IRenderContext2D, 类似Winform中的Graphics)和ISciChartRenderer(ViewConverter实现, 以IRenderContext2D为参数进行绘制);
  3. ViewConverter的RenderLoop中会调用NumericAxis和FastLineRenderableSeries的OnDraw方法, 而IRenderContext2D和IRenderPassData是OnDraw的两个参数

BindToDataSeriesSetView.xaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<UserControl x:Class="Abt.Controls.SciChart.Example.Examples.IWantTo.UseSciChartWithMvvm.BindToDataSeriesSetView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:SciChart="http://schemas.abtsoftware.co.uk/scichart"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

<!-- Button is used to invoke a delegate in the ViewModel to append 50 points. -->
<Button Grid.Row="0" Command="{Binding AppendDataCommand}" Content="Append 50 Points"/>

<!-- Declare a SciChartSurface and bind to data -->
<SciChart:SciChartSurface Grid.Row="1" SciChart:ThemeManager.Theme="ExpressionLight">

<SciChart:SciChartSurface.RenderableSeries>
<SciChart:FastLineRenderableSeries DataSeries="{Binding ChartData}" SeriesColor="#279B27"/>
</SciChart:SciChartSurface.RenderableSeries>

<SciChart:SciChartSurface.XAxis>
<SciChart:NumericAxis AutoRange="Always"/>
</SciChart:SciChartSurface.XAxis>

<SciChart:SciChartSurface.YAxis>
<SciChart:NumericAxis AutoRange="Always" GrowBy="0.1, 0.1"/>
</SciChart:SciChartSurface.YAxis>

</SciChart:SciChartSurface>
</Grid>
</UserControl>

程序仅绘制了一条曲线和XY坐标轴

工具: ILSpy
dll: Abt.Controls.SciChart.Wpf.dll(3.1.4549版本)

程序中是
绘制1个FastLineRenderableSeries
绘制2个NumericAxis


先看NumericAxis

NumericAxis

public class NumericAxis : AxisBase
public abstract class AxisBase : ContentControl, INotifyPropertyChanged, IXmlSerializable, IDrawable, IAxisParams, IHitTestable, ISuspendable, IInvalidatableElement, IAxis

IDrawable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
namespace Abt.Controls.SciChart.Visuals
{
/// <summary>
/// Defines the base interface for an object that can be drawn
/// </summary>
public interface IDrawable
{
/// <summary>
/// Gets or sets the width of the <see cref="T:Abt.Controls.SciChart.Visuals.IDrawable" /> in pixels
/// </summary>
double Width
{
get;
set;
}

/// <summary>
/// Gets or sets the height of the <see cref="T:Abt.Controls.SciChart.Visuals.IDrawable" /> in pixels
/// </summary>
double Height
{
get;
set;
}

/// <summary>
/// Called when the instance is drawn
/// </summary>
/// <param name="renderContext">The <see cref="T:Abt.Controls.SciChart.Rendering.Common.IRenderContext2D" /> used for drawing</param>
/// <param name="renderPassData">Contains arguments and parameters for this render pass</param>
void OnDraw(IRenderContext2D renderContext, IRenderPassData renderPassData);
}
}

回看AxisBase类中有OnDraw方法, 有计算ticks, 绘制坐标网格, 绘制坐标轴; NumericAxis使用OnDraw进行绘制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/// <summary>
/// Called when the instance is drawn
/// </summary>
/// <param name="renderContext">The <see cref="T:Abt.Controls.SciChart.Rendering.Common.IRenderContext2D" /> used for drawing</param>
/// <param name="renderPassData">Contains arguments and parameters for this render pass</param>
/// <seealso cref="T:Abt.Controls.SciChart.Visuals.IDrawable" />
/// <seealso cref="T:Abt.Controls.SciChart.Rendering.Common.IRenderContext2D" />
public void OnDraw(IRenderContext2D renderContext, IRenderPassData renderPassData)
{
if (!this.IsSuspended && this.DisconnectSelection() && this.IsLicenseValid)
{
using (IUpdateSuspender updateSuspender = this.SuspendUpdates())
{
updateSuspender.ResumeTargetOnDispose = false;
Stopwatch stopwatch = Stopwatch.StartNew();
if (this.LabelProvider != null)
{
this.LabelProvider.OnBeginAxisDraw();
}
this.uriInstance = this.CalculateTicks();
if (this.IsPrimaryAxis)
{
this.DrawGridLines(renderContext, this.uriInstance);
}
if (base.Visibility == Visibility.Visible && this.ConnectContext())
{
this.OnDrawAxis(this.uriInstance);
}
stopwatch.Stop();
SciChartDebugLogger.Instance.WriteLine("Drawn {0}: Width={1}, Height={2} in {3}ms", new object[]
{
base.GetType().Name,
base.ActualWidth,
base.ActualHeight,
stopwatch.ElapsedMilliseconds
});
}
return;
}
}

再看FastLineRenderableSeries

FastLineRenderableSeries

public class FastLineRenderableSeries : BaseRenderableSeries
FastLineRenderableSeries中发现方法InternalDraw

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/// <summary>
/// Draws the series using the <see cref="T:Abt.Controls.SciChart.Rendering.Common.IRenderContext2D" /> and the <see cref="T:Abt.Controls.SciChart.Visuals.RenderableSeries.IRenderPassData" /> passed in
/// </summary>
/// <param name="renderContext">The render context. This is a graphics object which has methods to draw lines, quads and polygons to the screen</param>
/// <param name="renderPassData">The render pass data. Contains a resampled <see cref="T:Abt.Controls.SciChart.Model.DataSeries.IPointSeries" />, the <see cref="T:Abt.Controls.SciChart.IndexRange" /> of points on the screen
/// and the current YAxis and XAxis <see cref="T:Abt.Controls.SciChart.Numerics.CoordinateCalculators.ICoordinateCalculator`1" /> to convert data-points to screen points</param>
protected override void InternalDraw(IRenderContext2D renderContext, IRenderPassData renderPassData)
{
Func<double, double, Color> func = null;
IPointSeries pointSeries = base.CurrentRenderPassData.PointSeries;
LinesEnumerable linesEnumerable = new LinesEnumerable(pointSeries, renderPassData.XCoordinateCalculator, renderPassData.YCoordinateCalculator, this.IsDigitalLine);
Func<Color, IPen2D> func2 = null;
FastLineRenderableSeries.ToolbarCollection toolbarCollection = new FastLineRenderableSeries.ToolbarCollection();
toolbarCollection.uriInstance = new DeploymentInvoker(renderContext, base.AntiAliasing, (float)base.StrokeThickness, base.Opacity);
try
{
if (base.SeriesColor.A != 0)
{
if (base.PaletteProvider != null)
{
IEnumerable<Point> arg_98_1 = linesEnumerable;
bool arg_98_2 = base.DrawNaNAs == LineDrawMode.ClosedLines;
if (func == null)
{
func = new Func<double, double, Color>(this.DisconnectSelection);
}
Func<double, double, Color> arg_98_3 = func;
if (func2 == null)
{
func2 = new Func<Color, IPen2D>(toolbarCollection.ViewReference);
}
renderContext.DrawLinesReusablePens(arg_98_1, arg_98_2, arg_98_3, func2);
}
else
{
this.DisconnectSelection(renderContext, base.SeriesColor, linesEnumerable, base.DrawNaNAs == LineDrawMode.ClosedLines, (this.StrokeDashArray != null) ? this.StrokeDashArray.ToArray<double>() : null);
}
}
}
finally
{
if (toolbarCollection.uriInstance != null)
{
((IDisposable)toolbarCollection.uriInstance).Dispose();
}
}
IPointMarker pointMarker = base.GetPointMarker();
if (pointMarker != null)
{
if (this.IsDigitalLine)
{
linesEnumerable = new LinesEnumerable(pointSeries, renderPassData.XCoordinateCalculator, renderPassData.YCoordinateCalculator, false);
}
using (IPen2D pen2D = renderContext.CreatePen(base.SeriesColor, base.AntiAliasing, (float)base.StrokeThickness, base.Opacity, null, PenLineCap.Round))
{
IPointMarker arg_156_0 = pointMarker;
IEnumerable<Point> arg_14E_0 = linesEnumerable;
if (FastLineRenderableSeries.CS$<>9__CachedAnonymousMethodDelegate4 == null)
{
FastLineRenderableSeries.CS$<>9__CachedAnonymousMethodDelegate4 = new Func<Point, bool>(FastLineRenderableSeries.DisconnectSelection);
}
arg_156_0.Draw(renderContext, arg_14E_0.Where(FastLineRenderableSeries.CS$<>9__CachedAnonymousMethodDelegate4), pen2D, null);
}
}
}

搜索DrawLinesReusablePens, 发现只有RenderContextBase实现IRenderContext2D接口, 然后DrawLinesReusablePens内部foreach遍历调用DrawLineSegment
后者调用DrawLine

那么谁调用了InternalDraw
protected override void InternalDraw 是虚方法,那么在父类BaseRenderableSeries中找, 发现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void IDrawable.ProcessContext(IRenderContext2D uriInstance, IRenderPassData windowCache)
{
this.CurrentRenderPassData = windowCache;
if (this.IsValidForDrawing)
{
if (this.uriInstance != uriInstance.ViewportSize)
{
this.OnParentSurfaceViewportSizeChanged();
this.uriInstance = uriInstance.ViewportSize;
}
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
this.InternalDraw(uriInstance, windowCache);
stopwatch.Stop();
SciChartDebugLogger.Instance.WriteLine("{0} DrawTime: {1}ms", new object[]
{
base.GetType().Name,
stopwatch.ElapsedMilliseconds
});
}
}

而且没有找到OnDraw方法,初步推断IDrawable.ProcessContext就是OnDraw


结束了FastLineRenderableSeries和NumericAxis, 再来看
SciChartSurface
它是如何调用FastLineRenderableSeries和NumericAxis的OnDraw

SciChartSurface的父类是SciChartSurfaceBase (SciChartSurfaceBase 继承Control,base指Control),里面有一个虚方法

1
2
3
4
/// <summary>
/// The inner drawing loop. Called once per frame. Do your drawing here.
/// </summary>
protected abstract void DoDrawingLoop();

由于是protected,该方法在public virtual void InvalidateElement()中被用到,终于出现public了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/// <summary>
/// Asynchronously requests that the element redraws itself plus children.
/// Will be ignored if the element is ISuspendable and currently IsSuspended (within a SuspendUpdates/ResumeUpdates call)
/// </summary>
public virtual void InvalidateElement()
{
if (this.IsSuspended)
{
SciChartDebugLogger.Instance.WriteLine("SciChartSurface.IsSuspended=true. Ignoring InvalidateElement() call", new object[0]);
return;
}
if (!OptionsList.SearchOptions() && this.RenderPriority != RenderPriority.Immediate)
{
if (this.uriInstance != null)
{
this.uriInstance.InvalidateElement();
}
return;
}
this.Services.GetService<ProjectSettings>().SelectClient(new Action(this.DoDrawingLoop), DispatcherPriority.Normal);
}

InvalidateElement在SciChartSurfaceBase中的OnSciChartSurfaceLoaded中被调用, 后者在OnLoad中被调用

1
2
3
4
5
6
7
/// <summary>
/// Forces initialization of the SciChartSurface in the case it is being used to render off-screen (on server)
/// </summary>
public void OnLoad()
{
this.OnSciChartSurfaceLoaded();
}

回到SciChartSurface看DoDrawingLoop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
protected override void DoDrawingLoop()
{
if (this.windowCache)
{
return;
}
try
{
using (IRenderContext2D renderContext = this.uriInstance.GetRenderContext()) // private IRenderSurface2D uriInstance;
{
try
{
RendererErrorCode rendererErrorCode = this.uriInstance.RenderLoop(renderContext); // private ISciChartRenderer uriInstance;
if (!GroupSettings.keywordsMap.Equals(rendererErrorCode) && base.DebugWhyDoesntSciChartRender)
{
Console.WriteLine(" SciChartSurface didn't render, " + rendererErrorCode);
}
}
catch (Exception caught)
{
base.OnRenderFault(caught);
}
}
}
catch (Exception caught2)
{
base.OnRenderFault(caught2);
}
}

搜索GetRenderContextRenderLoop, 可知
private IRenderSurface2D uriInstance可以认为是HighSpeedRenderSurface
private ISciChartRenderer uriInstance;是ViewConverter


HighSpeedRenderSurface

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
namespace Abt.Controls.SciChart.Rendering.HighSpeedRasterizer
{
/// <summary>
/// Provides a <see cref="T:Abt.Controls.SciChart.Rendering.Common.RenderSurfaceBase" /> implementation that uses a High-Speed software rasterizer, capable of outputting many millions of points (line-series)
/// at interactive framerates. The downside is, the <see cref="T:Abt.Controls.SciChart.Rendering.HighSpeedRasterizer.HighSpeedRenderSurface" /> uses integer fixed-point math which results in jagged lines.
/// </summary>
/// <seealso cref="T:Abt.Controls.SciChart.Rendering.HighQualityRasterizer.HighQualityRenderSurface" />
/// <seealso cref="T:Abt.Controls.SciChart.Rendering.Common.RenderSurfaceBase" />
/// <seealso cref="T:Abt.Controls.SciChart.Rendering.Common.IRenderContext2D" />
[AbtLicenseProvider(typeof(XmlFileSite))]
public class HighSpeedRenderSurface : RenderSurfaceBase
{
/// <summary>
/// When overridden in a derived class, returns a RenderContext valid for the current render pass
/// </summary>
/// <returns></returns>
public override IRenderContext2D GetRenderContext()
{
return this.RenderWriteableBitmap.ViewReference(base.Image, this.uriInstance);
}
}
}

protected WriteableBitmap RenderWriteableBitmap;
WriteableBitmap
https://msdn.microsoft.com/en-us/library/system.windows.media.imaging.writeablebitmap(v=vs.110).aspx
WriteableBitmap使用的双缓冲技术

1
2
3
4
Use the WriteableBitmap class to update and render a bitmap on a per-frame basis. This is useful for generating algorithmic content, such as a fractal image, and for data visualization, such as a music visualizer.
The WriteableBitmap class uses two buffers. The back buffer is allocated in system memory and accumulates content that is not currently displayed. The front buffer is allocated in system memory and contains the content that is currently displayed. The rendering system copies the front buffer to video memory for display.
Two threads use these buffers. The user interface (UI) thread generates the UI but does not present it to the screen. The UI thread responds to user input, timers, and other events. An application can have multiple UI threads. The render thread composes and renders changes from the UI thread. There is only one render thread per application.
The UI thread writes content to the back buffer. The render thread reads content from the front buffer and copies it to video memory. Changes to the back buffer are tracked with changed rectangular regions.

ViewReference是扩展方法, 经常出现这个ViewReference, 不是特别清楚意义


ViewConverter

internal class ViewConverter : ISciChartRenderer
看ViewConverter的RenderLoop方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public RendererErrorCode RenderLoop(IRenderContext2D renderContext)
{
//...忽略
//
using (IUpdateSuspender updateSuspender = this.uriInstance.SuspendUpdates())
{
updateSuspender.ResumeTargetOnDispose = false;
SciChartDebugLogger.Instance.WriteLine("Beginning Render Loop ... ", new object[0]);
Size size = this.ViewReference(this.uriInstance);
if (this.ViewReference(this.uriInstance, size, out result))
{
RenderPassInfo renderPassInfo = ViewConverter.ViewReference(this.uriInstance, size);
renderContext.Clear();

//绘制坐标轴
ViewConverter.ViewReference(this.uriInstance, renderPassInfo, renderContext);

//绘制renderableSeries
ViewConverter.SelectClient(this.uriInstance, renderPassInfo, renderContext);

//更新Annotations
ViewConverter.ViewReference(this.uriInstance, renderPassInfo);
this.uriInstance.OnSciChartRendered();
}
}
return result;
}

绘制坐标轴, 出现OnDraw

1
2
3
4
5
6
7
8
9
10
11
12
13
14
internal static void ViewReference(ISciChartSurface uriInstance, RenderPassInfo windowCache, IRenderContext2D lastKeywords)
{
foreach (IAxis current in uriInstance.XAxes)
{
current.ValidateAxis();
current.OnDraw(lastKeywords, null);
}
foreach (IAxis current2 in uriInstance.YAxes)
{
current2.ValidateAxis();
current2.OnDraw(lastKeywords, null);
}
lastKeywords.Layers.Flush();
}

遍历绘制renderableSeries

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
internal static void SelectClient(ISciChartSurface uriInstance, RenderPassInfo windowCache, IRenderContext2D lastKeywords)
{
if (windowCache.RenderableSeries == null)
{
return;
}
List<int> list = new List<int>();
for (int i = 0; i < windowCache.RenderableSeries.Length; i++)
{
IRenderableSeries renderableSeries = windowCache.RenderableSeries[i];
if (renderableSeries != null)
{
renderableSeries.XAxis = uriInstance.XAxes.GetAxisById(renderableSeries.XAxisId, true);
renderableSeries.YAxis = uriInstance.YAxes.GetAxisById(renderableSeries.YAxisId, true);
if (windowCache.RenderableSeries[i].IsSelected)
{
list.Add(i);
}
else
{
ViewConverter.ViewReference(uriInstance, windowCache, lastKeywords, i);
}
}
}
foreach (int current in list)
{
ViewConverter.ViewReference(uriInstance, windowCache, lastKeywords, current);
}
uriInstance.Services.GetService<IEventAggregator>().Publish<SciChartRenderedMessage>(new SciChartRenderedMessage(uriInstance, lastKeywords));
}

1
2
3
4
5
6
7
8
9
10
11
private static void ViewReference(ISciChartSurface uriInstance, RenderPassInfo windowCache, IRenderContext2D lastKeywords, int categoryDisposed)
{
IRenderableSeries renderableSeries = windowCache.RenderableSeries[categoryDisposed];
ICoordinateCalculator<double> yCoordinateCalculator;
ICoordinateCalculator<double> xCoordinateCalculator;
if (windowCache.YCoordinateCalculators.TryGetValue(renderableSeries.YAxisId, out yCoordinateCalculator) && windowCache.XCoordinateCalculators.TryGetValue(renderableSeries.XAxisId, out xCoordinateCalculator))
{
RenderPassData renderPassData = new RenderPassData(windowCache.IndicesRanges[categoryDisposed], xCoordinateCalculator, yCoordinateCalculator, windowCache.PointSeries[categoryDisposed]);
renderableSeries.OnDraw(lastKeywords, renderPassData);
}
}

最后看一下IRenderContext2D和IRenderPassData

IRenderContext2D

相当于Winform中的Graphics

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
namespace Abt.Controls.SciChart.Rendering.Common
{
//删掉了一些
/// <summary>
/// Defines the interface to a 2D RenderContext, allowing drawing, blitting and creation of pens and brushes on the <see cref="T:Abt.Controls.SciChart.Rendering.Common.RenderSurfaceBase" />
/// </summary>
/// <remarks>The <see cref="T:Abt.Controls.SciChart.Rendering.Common.IRenderContext2D" /> is a graphics context valid for the current render pass. Any class which implements <see cref="T:Abt.Controls.SciChart.Visuals.IDrawable" /> has an OnDraw method
/// in which an <see cref="T:Abt.Controls.SciChart.Rendering.Common.IRenderContext2D" /> is passed in. Use this to draw penned lines, fills, rectangles, ellipses and blit graphics to the screen.</remarks>
public interface IRenderContext2D : IDisposable
{
/// <summary>
/// Gets a collection of <see cref="T:Abt.Controls.SciChart.Rendering.Common.RenderOperationLayers" />, which allow rendering operations to be posted to a layered queue for later
/// execution in order (and correct Z-ordering).
/// </summary>
/// <example>
/// <code title="RenderOperationLayers Example" description="Demonstrates how to enqueue operations to the RenderOperationLayers collection and later flush to ensure rendering operations get processed in the correct Z-order" lang="C#">
/// RenderOperationLayers layers = renderContext.Layers;
///
/// // Enqueue some operations in the layers in any order
/// layers[RenderLayer.AxisMajorGridlines].Enqueue(() =&gt; renderContext.DrawLine(/* .. */));
/// layers[RenderLayer.AxisBands].Enqueue(() =&gt; renderContext.DrawRectangle(/* .. */));
/// layers[RenderLayer.AxisMinorGridlines].Enqueue(() =&gt; renderContext.DrawLine(/* .. */));
///
/// // Processes all layers by executing enqueued operations in order of adding,
/// // and in Z-order of layers
/// layers.Flush();</code>
/// </example>
RenderOperationLayers Layers
{
get;
}

/// <summary>
/// Gets the current size of the viewport.
/// </summary>
Size ViewportSize
{
get;
}

IBrush2D CreateBrush(Color color, double opacity = 1.0, bool? alphaBlend = null);

IPen2D CreatePen(Color color, bool antiAliasing, float strokeThickness, double opacity = 1.0, double[] strokeDashArray = null, PenLineCap strokeEndLineCap = PenLineCap.Round);

ISprite2D CreateSprite(FrameworkElement fe);

void Clear();

void DrawSprite(Point destPoint, ISprite2D srcSprite, Rect srcRect);

void FillRectangle(IBrush2D brush, Point pt1, Point pt2, double gradientRotationAngle);

void FillPolygon(IBrush2D brush, IEnumerable<Point> points);

void FillArea(IBrush2D brush, IEnumerable<Tuple<Point, Point>> lines, double gradientRotationAngle = 0.0, bool isVerticalChart = false);

void DrawQuad(IPen2D pen, Point pt1, Point pt2);

void DrawEllipse(double width, double height, Point center, IBrush2D brush, IPen2D pen);

void DrawLine(IPen2D pen, Point pt1, Point pt2);

}


IRenderPassData

这个接口将原始数据变换到Chart所在的视窗上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
using Abt.Controls.SciChart.Model.DataSeries;
using Abt.Controls.SciChart.Numerics.CoordinateCalculators;
using System;

namespace Abt.Controls.SciChart.Visuals.RenderableSeries
{
/// <summary>
/// Defines the interface to <see cref="T:Abt.Controls.SciChart.Visuals.RenderableSeries.RenderPassData" />, the data used in a single render pass by <see cref="T:Abt.Controls.SciChart.Visuals.RenderableSeries.BaseRenderableSeries" /> derived types
/// </summary>
public interface IRenderPassData
{
/// <summary>
/// Gets the integer indices of the X-Data array that are currently in range.
/// </summary>
/// <returns>The indices to the X-Data that are currently in range</returns>
/// <example>If the input X-data is 0...100 in steps of 1, the VisibleRange is 10, 30 then the PointRange will be 10, 30</example>
/// <remarks></remarks>
IndexRange PointRange
{
get;
}

/// <summary>
/// Gets the current point series.
/// </summary>
IPointSeries PointSeries
{
get;
}

/// <summary>
/// Gets a value, indicating whether current chart is vertical
/// </summary>
bool IsVerticalChart
{
get;
}

/// <summary>
/// Gets the current Y coordinate calculator.
/// </summary>
ICoordinateCalculator<double> YCoordinateCalculator
{
get;
}

/// <summary>
/// Gets the current X coordinate calculator.
/// </summary>
ICoordinateCalculator<double> XCoordinateCalculator
{
get;
}
}
}